package tech.yixiyun.framework.kuafu.enhance.hancer;


import tech.yixiyun.framework.kuafu.component.Component;

import java.lang.reflect.Method;

/**
 * 面向切面的增强类。通过这个接口自己实现一些增强方法，比如为方法加事务管理，日志管理等等。
 * 一旦一个类使用了 @Enhance 注解，就会为它生成一个代理类，代理类继承了原始类，代理类的方法和原始类的方法一样，底层也是调用的
 * 原始类方法，只不过在调用原始类的方法前后，都会执行你写的Enhancer的beforeDo和afterDo。
 * 详情请自己查询动态代理相关知识。
 */
@Component
public interface IEnhancer {

    /**
     * 原方法执行前你要干啥。在这里不要调用method.invoke
     * @param instance 执行方法的实例，但注意！！！这个实例是代理类的实例，而不是原始类的实例，
     * @param method 这个方法是原方法，也就是被代理类的方法，原汁原味，不要在这里调用方法！！！！
     * @param args 传进来的方法执行参数
     */
    void beforeDo(Object instance, Method method, Object[] args);

    /**
     * 原方法正常执行后你要干啥
     * @param instance 执行方法的实例，但注意！！！这个实例是代理类的实例，而不是原始类的实例，
     * @param method 这个方法是原方法，也就是被代理类的方法，原汁原味，不要在这里调用方法！！！！
     * @param args 传进来的方法执行参数
     * @param returnValue 方法返回后返回值
     */
    void afterDo(Object instance, Method method, Object[] args, Object returnValue);

    /**
     * 原方法执行后如果发生异常，你要干啥。默认会继续抛出Exception
     * @param instance 执行方法的实例，但注意！！！这个实例是代理类的实例，而不是原始类的实例，
     * @param method 这个方法是原方法，也就是被代理类的方法，原汁原味，不要在这里调用方法！！！！
     * @param args 传进来的方法执行参数
     * @param e catch到的异常
     */
    default void afterExceptionDo(Object instance, Method method, Object[] args, Throwable e) {
        throw new EnhancerException(e);
    }


    /**
     * 无论方法执行是否成功，你想干的事。默认啥都不干
     * @param instance 执行方法的实例，但注意！！！这个实例是代理类的实例，而不是原始类的实例，
     * @param method 这个方法是原方法，也就是被代理类的方法，原汁原味，不要在这里调用方法！！！！
     * @param args 传进来的方法执行参数
     */
    default void finishDo(Object instance, Method method, Object[] args) {}
}
